package com.sunxboy.platform.thread;

import java.util.Comparator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * Thread pool executor that uses priority queue for the tasks
 */
public class PriorityThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
    private static final long serialVersionUID = 1L;
    private Comparator<?> comparator;
    private ThreadFactory threadFactory;
    private int initialCapacity = 11;

    public PriorityThreadPoolTaskExecutor() {
        this("AppCore");
    }

    public PriorityThreadPoolTaskExecutor(String threadFactoryName) {
        setThreadFactory(new NamedThreadFactory(threadFactoryName));
    }

    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }

    public void setThreadFactory(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
        super.setThreadFactory(this.threadFactory);
    }

    public Comparator<?> getComparator() {
        return comparator;
    }

    public void setComparator(Comparator<?> comparator) {
        this.comparator = comparator;
    }

    public void setInitialCapacity(int initialCapacity) {
        this.initialCapacity = initialCapacity;
    }

    @Override
    public void setQueueCapacity(int queueCapacity) {
        /*
         * Priority queue cannot be bounded otherwise, you cannot guarantee ordering of the elements.
         */
        throw new IllegalArgumentException("PriorityThreadPoolTaskExecutor does not support bounded queues");
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    protected BlockingQueue createQueue(int queueCapacity) {
        if (comparator != null) {
            return new PriorityBlockingQueue(this.initialCapacity, comparator);
        }
        else {
            return new PriorityBlockingQueue(this.initialCapacity);
        }
    }

}
